return {
    {
        "neovim/nvim-lspconfig",
        event = { "BufReadPost", "BufNewFile" },
        dependencies = {
            "williamboman/mason-lspconfig.nvim",
            {
                "simrat39/rust-tools.nvim",
                config = function()
                    local rt = require("rust-tools")

                    rt.setup({
                        server = {
                            on_attach = function(_, bufnr)
                                -- Hover actions
                                vim.keymap.set("n", "<Leader>q", rt.hover_actions.hover_actions, {
                                    buffer = bufnr,
                                })
                                -- Code action groups
                                vim.keymap.set("n", "<Leader>a", rt.code_action_group.code_action_group, {
                                    buffer = bufnr,
                                })
                            end,
                        },
                    })
                end,
            },
            {
                "scalameta/nvim-metals",
                config = function()
                    local metals_config = require("metals").bare_config()
                    metals_config.settings = {
                        showImplicitArguments = true,
                    }
                    metals_config.init_options.statusBarProvider = "on"
                    local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp")
                    if status_ok then
                        metals_config.capabilities = require("cmp_nvim_lsp").default_capabilities()
                    end

                    -- Autocmd that will actually be in charging of starting the whole thing
                    local nvim_metals_group = vim.api.nvim_create_augroup("nvim-metals", {
                        clear = true,
                    })
                    vim.api.nvim_create_autocmd("FileType", {
                        pattern = { "scala", "sbt" },
                        callback = function()
                            require("metals").initialize_or_attach(metals_config)
                        end,
                        group = nvim_metals_group,
                    })
                end,
            },
        },
        config = function()
            -- Set up cool signs for diagnostics
            local signs = {
                Error = " ",
                Warn = " ",
                Hint = " ",
                Info = " ",
            }
            for type, icon in pairs(signs) do
                local hl = "DiagnosticSign" .. type
                vim.fn.sign_define(hl, {
                    text = icon,
                    texthl = hl,
                    numhl = "",
                })
            end

            -- Diagnostic config
            local config = {
                virtual_text = false,
                signs = {
                    active = signs,
                },
                update_in_insert = true,
                underline = true,
                severity_sort = true,
                float = {
                    focusable = true,
                    style = "minimal",
                    border = "rounded",
                    source = "always",
                    header = "",
                    prefix = "",
                },
            }
            vim.diagnostic.config(config)
            vim.api.nvim_set_keymap("n", "<space>dd", "<cmd>lua vim.diagnostic.open_float()<CR>", {
                noremap = true,
                silent = true,
                desc = "open diagnostic",
            })

            -- This function gets run when an LSP connects to a particular buffer.
            local on_attach = function(client, bufnr)
                local opts = {
                    noremap = true,
                    silent = true,
                }
                vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opts)
                vim.api.nvim_buf_set_keymap(
                    bufnr,
                    "n",
                    "<leader>wa",
                    "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>",
                    opts
                )
                vim.api.nvim_buf_set_keymap(
                    bufnr,
                    "n",
                    "<leader>wr",
                    "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>",
                    opts
                )
                vim.api.nvim_buf_set_keymap(
                    bufnr,
                    "n",
                    "<leader>wl",
                    "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>",
                    opts
                )
                vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>D", "<cmd>lua vim.lsp.buf.type_definition()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>", opts)
                vim.api.nvim_buf_set_keymap(
                    bufnr,
                    "n",
                    "<leader>e",
                    "<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>",
                    opts
                )
                vim.api.nvim_buf_set_keymap(bufnr, "n", "[d", "<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>", opts)
                vim.api.nvim_buf_set_keymap(bufnr, "n", "]d", "<cmd>lua vim.lsp.diagnostic.goto_next()<CR>", opts)
                vim.api.nvim_buf_set_keymap(
                    bufnr,
                    "n",
                    "<leader>q",
                    "<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>",
                    opts
                )

                -- Create a command `:Format` local to the LSP buffer
                vim.api.nvim_buf_create_user_command(bufnr, "Format", function(_)
                    vim.lsp.buf.format()
                end, {
                    desc = "Format current buffer with LSP",
                })
            end

            local servers = {
                "bashls",
                "clangd",
                "cmake",
                "cssls",
                "jsonls",
                "html",
                "lua_ls", -- "tsserver",
                -- "yamlls",
                "marksman",
                "pyright",
                "slint_lsp",
                "svlangserver",
            }
            -- 大部分lsp采用默认设置即可
            for _, server in pairs(servers) do
                require("lspconfig")[server].setup({})
            end

            -- Lua
            require("lspconfig")["lua_ls"].setup({
                on_attach = on_attach,
                settings = {
                    Lua = {
                        runtime = {
                            version = "Lua 5.1",
                        },
                        completion = {
                            callSnippet = "Replace",
                        },
                        diagnostics = {
                            globals = { "vim" },
                        },
                        workspace = {
                            library = {
                                [vim.fn.expand("$VIMRUNTIME/lua")] = true,
                                [vim.fn.stdpath("config") .. "/lua"] = true,
                            },
                        },
                    },
                },
            })

            local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp")
            if status_ok then
                require("lspconfig").clangd.setup({
                    on_attach = on_attach,
                    capabilities = cmp_nvim_lsp.default_capabilities(),
                    cmd = { "clangd", "--offset-encoding=utf-16" },
                })
            end
            -- Python
            require("lspconfig")["pylsp"].setup({
                on_attach = on_attach,
                capabilities = capabilities,
                settings = {
                    pylsp = {
                        plugins = {
                            flake8 = {
                                enabled = true,
                                maxLineLength = 88, -- Black's line length
                            },
                            -- Disable plugins overlapping with flake8
                            pycodestyle = {
                                enabled = false,
                            },
                            mccabe = {
                                enabled = false,
                            },
                            pyflakes = {
                                enabled = false,
                            },
                            -- Use Black as the formatter
                            autopep8 = {
                                enabled = false,
                            },
                        },
                    },
                },
            })
        end,
    },
}
